"""
用户信息模块
"""

import copy

from werkzeug.security import generate_password_hash

from app.dao import (Base, get_db_session, Column, String, INTEGER, TIMESTAMP, paginate)
from app.common.constants import UserInfoConstants
from app.dto.userinfo import UserInfoDto
from app.utils.dateutil import get_current_time_str


class UserInfo(Base):
    """
    用户信息类
    """

    # 数据库表名
    __tablename__ = "user_info"

    # 主键ID
    id = Column('id', INTEGER, primary_key=True, autoincrement=True)
    # 用户名称
    name = Column('name', String(32), nullable=False)
    # 真实名称
    real_name = Column('real_name', String(32), default="")
    # 密码
    password = Column('password', String(128), nullable=False)
    # 手机号码
    mobile = Column('mobile', String(11), nullable=False)
    # 头像
    avatar = Column('avatar', String(128), default='')
    # 状态
    status = Column('status', INTEGER, nullable=False)
    # 添加时间
    add_time = Column('add_time', TIMESTAMP, nullable=False,
                      default=get_current_time_str())
    # 修改时间
    modify_time = Column('modify_time', TIMESTAMP)

    def __str__(self):
        return "({0.id!s}, {0.name!s}, {0.real_name!s}, {0.password!s}, {0.mobile!s},{0.avatar!s}, {0.status!s})".format(
            self)


class UserInfoDao(object):
    """
    用户信息Dao类
    """

    @classmethod
    def save(cls, item):
        """
        保存
        :param item:
        :return:
        """
        with get_db_session() as session:
            obj = UserInfo(name=item.name, real_name=item.real_name, password=generate_password_hash(item.password),
                           mobile=item.mobile, avatar=item.avatar, status=item.status)
            session.add(obj)
            session.commit()
            return obj

    @classmethod
    def save_all(cls, item_list):
        """
        批量保存（使用SQLAlchemy Core进行性能优化，只需发送一条SQL）
        :param item_list:
        :return:
        """

        obj_list = []
        for item in item_list:
            obj = UserInfo(name=item.name, real_name=item.real_name, password=generate_password_hash(item.password),
                           mobile=item.mobile, avatar=item.avatar, status=item.status).__dict__
            obj_list.append(obj)

        with get_db_session() as session:
            session.execute(UserInfo.__table__.insert(), obj_list)
            session.commit()
        return obj_list

    @classmethod
    def remove_by_id(cls, _id):
        """
        根据id进行逻辑删除
        :param _id:
        :return:
        """
        with get_db_session() as session:
            result = session.query(UserInfo).filter_by(id=_id).update(dict(
                status=UserInfoConstants.Status.DELETE.value[0],
                modify_time=get_current_time_str()
            ))
            session.commit()

        return result

    @classmethod
    def update(cls, item):
        """
        更新
        :param item:
        :return:
        """
        with get_db_session() as session:
            result = session.query(UserInfo).filter_by(id=item.id).update(dict(
                name=item.name,
                real_name=item.real_name,
                password=item.password,
                mobile=item.mobile,
                avatar=item.avatar,
                status=item.status,
                modify_time=get_current_time_str()
            ))
            session.commit()

        return result

    @classmethod
    def find_by_id(cls, id_):
        """
        根据id获取
        :param id_:
        :return:
        """
        with get_db_session() as session:
            result = session.query(UserInfo).filter_by(id=id_).first()
            if result:
                return copy.deepcopy(result)

    @classmethod
    def find_by_name(cls, name):
        """
        根据name获取
        :param name:
        :return:
        """
        with get_db_session() as session:
            result = session.query(UserInfo).filter_by(name=name).first()
            if result:
                return copy.deepcopy(result)

    @classmethod
    def find_by_id_status(cls, id_, status=UserInfoConstants.Status.NORMAL.value[0]):
        """
        根据用户id和status获取
        :param id_:
        :param status:
        :return:
        """
        with get_db_session() as session:
            result = session.query(UserInfo).filter_by(id=id_, status=status).first()
            if result:
                return copy.deepcopy(result)

    @classmethod
    def find_all(cls):
        """
        获取所有
        :return:
        """

        with get_db_session() as session:
            result = session.query(UserInfo).all()
            if result:
                # 需要使用深度拷贝
                return copy.deepcopy(result)

    @classmethod
    def page_by_param(cls, page=1, page_size=10, **kwargs):
        """
        分页查询
        :param page:
        :param page_size:
        :param kwargs:
        :return:
        """

        if page < 1:
            page = 1

        # 比filter_by的功能更强大，支持比较运算符，支持or、in_等语法。
        filters = set()

        if 'name' in kwargs:
            name = kwargs['name']
            if name:
                filters.add(UserInfo.name.ilike('%' + name + '%'))

        if 'real_name' in kwargs:
            real_name = kwargs['real_name']
            if real_name:
                filters.add(UserInfo.real_name.ilike('%' + real_name + '%'))

        if 'status' in kwargs:
            filters.add(UserInfo.status == kwargs['status'])

        with get_db_session() as session:
            page_query = session.query(UserInfo).filter(*filters).order_by(
                UserInfo.status.asc(),
                UserInfo.id.desc())
            pagination = paginate(page_query, page=page, page_size=page_size)
            result = dict(
                items=copy.deepcopy(pagination.items),
                previous_page=pagination.previous_page,
                next_page=pagination.next_page,
                has_previous=pagination.has_previous,
                has_next=pagination.has_next,
                total=pagination.total,
                pages=pagination.pages,
                page=page,

            )

            return result


if __name__ == "__main__":
    # user = UserInfoDto(name='kevin', password='12345', mobile='13148457968')
    # UserInfoDao.save(user)
    # user_list = UserInfoDao.find_all()
    # for user in user_list:
    #     print(user)
    pass
